-
Notifications
You must be signed in to change notification settings - Fork 60
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Optimistic locking #56
base: master
Are you sure you want to change the base?
Optimistic locking #56
Conversation
Codecov Report
@@ Coverage Diff @@
## master #56 +/- ##
==========================================
- Coverage 85.44% 82.36% -3.08%
==========================================
Files 18 18
Lines 371 397 +26
==========================================
+ Hits 317 327 +10
- Misses 28 40 +12
- Partials 26 30 +4
Continue to review full report at Codecov.
|
Hi @arthurclement-lab49 PRs that have more than 10line changes, it would be good to raise a feature request issue for them to talk about the feature before creating a PR, this will save your time. I'll close this PR, feel free to reopen it if needed. |
Hi @mehran-prs Thanks for looking into this. Can I just ask you look into my observations below before you definitely close this PR. Optimistic locking is an essential feature for whatever project I have to implement, and I'm sure lots of other users, and although mongodb now has transactions, you dont always want to use them, especially when updating a single document. I appreciate that having it in baked in the defaultModel is perhaps too much as it will indeed add a version field that you might not want for your documents (although there is always the option of redefining your own DefaultModel as you mention).
The PR is actually flexible when it comes to this version field though as you just need to implement the Versionable interface. But you also need to consider the most important part of the PR which is the update function of the operation.go file and will actually check whether the document you are saving has the right matching version. |
Hi @arthurclement-lab49 |
…ve specific error type
Hi mehran-prs I've implemented your feedback. Its probably lacking a proper test at this stage to make sure everything works as expected. Will try to get to it later. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the changes.
Let's say a user implements After this change, we don't need to check if the version is zero in the |
- Name version field name Version_ to avoid collisions. - In operation.update(), capture Version before hooks in case updatedAt is used as versionable field - In operation.create(), if model is versionable and zero, increment version so it gets initialized in DB - Rename GetVersionFieldName to GetVersionBsonFieldName to make it clear it is the bson field name. - Rename GetVersion() to Version() as it is more idiomatic
Yes ok, version will therefore start at 1 for the int strategy with this change which is ok, just need to be aware of it. I've also done a couple of other changes as described in the last commit message :
As discussed
Necessary if you want to use udpatedAt as the version field. I have thought more about this case and think that it would require even more changes if we wanted to support this case out of the box, eg have a struct DateFieldsVersionable that would implement the Versionable interface. Perhaps we can envisage this later but its worth keeping in mind.
As discussed
I think it is clearer
go uses the simpler form for getters so I aligned with that. |
Hi,
I needed to have optimistic locking behavior on my project so implemented it in this pull request. It is based on a version field that gets incremented when saving. It can also be done through an updatedOn field but this PR uses the version technique for the DefaultModel.
It works the following way :
A new field called "Version" has been added to DefaultModel (saves to "version" in the db)
Models have to implement a Versionable interface so that the behavior kicks in. DefaultModel implements it and so documents using the DefaultModel will have this enabled by default). This interface has 3 methods :
GetVersion() -> returns the version number of this document
IncrementVersion() -> responsible for updating the version number
GetVersionFieldName() -> returns the name of the field that holds the version number
Then when the actual update is called, we can simply check that in the query part of the udpate that the version is the same as when the document was retrieved. If not, a custom error is raised.